package in.ac.iitb.cse.nlp.poswordpredictor;

import in.ac.iitb.cse.nlp.postagger.data.Config;
import in.ac.iitb.cse.nlp.postagger.data.EmissionMatrix;
import in.ac.iitb.cse.nlp.postagger.data.TableCreator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

public class Trainer extends TableCreator {

	public String prevTagConf;
	static public ExtendedTransitionMatrix transitionMatrix = new ExtendedTransitionMatrix();
	static public EmissionMatrix emissionMatrix = new EmissionMatrix();
	static public InverseEmissionMatrix inverseEmissionMatrix = new InverseEmissionMatrix();
	static public WordMatrix wordMatrix = new WordMatrix();
	static public Set<String> tagSet = new HashSet<String>();

	// String previousTag = START_OF_SENTENCE;
	static public String prevTag = null;

	String prevWord = null;
	
	public void createNew(File file) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				new FileInputStream(file)));
		String line = null;
		prevTag = null;
		while ((line = reader.readLine()) != null) {
			processLine(line);
			processLineWordMatrix(line);
		}

	}

	public void goFile(String filename) {
		if (filename.endsWith("txt") == false)
			return;
		File file = new File(filename);
		try {
			createNew(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void goDir(String cdir, String dir) {
		if (cdir.endsWith("/") == false && dir.endsWith("/") == false)
			cdir.concat("/");
		File Dir = new File(cdir + dir);
		if (Dir.isDirectory()) {
			for (File f : Dir.listFiles()) {
				// Dont assume that file trained good...
				// return the exit Status, check it
				if (f.isFile() && f.canRead()) {
					goFile(f.getAbsolutePath());
				}
			}

		} else if (Dir.canRead() && Dir.isFile()) {
			// Dont assume that file trained good...
			// return the exit Status, check it
			goFile(Dir.getAbsolutePath());
		}
	}

	public String getPrevTagString() {
		return prevTag;
	}

	public void updateGram_Conf(String word, String currentTag) {
		if (currentTag.contains("-") == true) {
			String tag[] = currentTag.split("-");
			for (int i = 0; i < 2; i++) {
				tagSet.add(tag[i]); // add Tag to set
				transitionMatrix.updateCount(tag[i]); // Unigram count
				if (prevTag != null)
					transitionMatrix.update(prevTag, tag[i]); // Bigram count
				if (prevTagConf != null)
					transitionMatrix.update(prevTagConf, tag[i]); // Bigram
																	// count
				emissionMatrix.update(tag[i], word); // Emission Count
				inverseEmissionMatrix.update(tag[i], word);
			}
			prevTag = tag[0];
			prevTagConf = tag[1];
		} else {
			tagSet.add(currentTag); // add Tag to set
			transitionMatrix.updateCount(currentTag); // Unigram count
			if (prevTag != null)
				transitionMatrix.update(prevTag, currentTag); // Bigram count
			if (prevTagConf != null)
				transitionMatrix.update(prevTagConf, currentTag); // Bigram
																	// count
			emissionMatrix.update(currentTag, word); // Emission Count
			inverseEmissionMatrix.update(currentTag, word);
			prevTag = currentTag;
			prevTagConf = null;
		}
	}

	public void updateGram_Base(String word, String currentTag) {
		tagSet.add(currentTag); // add Tag to set
		transitionMatrix.updateCount(currentTag); // Unigram count
		if (prevTag != null) {
			transitionMatrix.update(prevTag, currentTag); // Bigram count
		}
		// For updating emission table
		emissionMatrix.update(currentTag, word); // Emission Count
		inverseEmissionMatrix.update(currentTag, word);
		prevTag = currentTag;
		prevTagConf = null;
	}

	public void updateGram(String word, String currentTag) {
		if (Config.isAmbigutyResolv == true)
			updateGram_Conf(word, currentTag);
		else
			updateGram_Base(word, currentTag);
	}

	public void beginLine() {
		String currentTag = "^";
		String word = "^";
		updateGram(word, currentTag);
	}

	public void endLine() {
		// only one $ tag at the end
		String currentTag = "$";
		String word = "$";
		updateGram(word, currentTag);
		prevTag = null; // Unset for new Sentence
	}

	public void beginLineWord(String word)
	{
		wordMatrix.update(START_OF_SENTENCE,word);
		prevWord=word;
	}
	
	public void endLineWord(String word)
	{ 
		wordMatrix.update(word, END_OF_SENTENCE);
		prevWord=null;
	}
	
	public void processLine(String line) {
		String[] split = line.split(WORD_SEPARATOR);
		for (String string : split) {
			String[] strings = string.split(TAG_SEPARATOR); // Dont assume start
															// of the line is
															// start of sentence
			if (strings.length >= 2) {
				if (prevTag == null)
					beginLine();

				updateGram(strings[1], strings[0]);

				/* End of Line */
				if (strings[1].equals(END_OF_SENTENCE)
						|| strings[1].equals(ALTERNATE_END_OF_SENTENCE)) {
					endLine();
				}

			}
		}
	}
	
	private void processLineWordMatrix(String line) {
		String[] split = line.split(WORD_SEPARATOR);
		for (String string : split) {
			String[] strings = string.split(TAG_SEPARATOR); //Dont assume start of the line is start of sentence
			if( strings.length >=2 )
			{
				if( prevWord == null ){
					beginLineWord(strings[1]);
				}else if(strings[1].equals(END_OF_SENTENCE) || 
						strings[1].equals(ALTERNATE_END_OF_SENTENCE)) {
					endLineWord(prevWord);
				}else{
					wordMatrix.update(prevWord,strings[1]);
					prevWord=strings[1];
				}
			}
		}
	}

}
